#pragma once

#include "head.h"
#include <openssl/evp.h>
#include <openssl/md5.h>

class Path
{
public:
    static string getRootPath(string uname)
    {
        return ROOT_PATH + uname;
    }

    static string getUpLevelPathSuffix(string path)
    {
        string subPath = path.substr(0, path.find_last_of('/'));
        return subPath.substr(subPath.find_last_of('/') + 1);
    }

    static string getUpLevelPath(string path)
    {
        return path.substr(0, path.find_last_of('/'));
    }

    static string subRootPath(string path)
    {
        return path.substr(0, path.find_first_of('/', strlen(ROOT_PATH)));
    }

    static string getFile(string path)
    {
        return path.substr(path.find_last_of('/') + 1);
    }

    static size_t getFileSize(string fpath)
    {
        struct stat st{};
        int ret = stat(fpath.c_str(), &st);
        if(ret == -1){
            perror("Path getFileSize");
        }
        return st.st_size;
    }

    static void getMd5Sum(const string &path, string &md5val, size_t size)
    {
        md5val.clear();

        int fd = open(path.c_str(), O_RDONLY);
        if (fd == -1)
        {
            // 处理文件打开失败
            return;
        }

        // 使用 EVP 接口
        EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
        const EVP_MD *md = EVP_md5(); // 获取 MD5 算法

        // 初始化上下文
        if (EVP_DigestInit_ex(mdctx, md, nullptr) != 1)
        {
            // 错误处理
            EVP_MD_CTX_free(mdctx);
            close(fd);
            return;
        }

        char buf[1024 * 16];
        ssize_t ret;
        while ( size > 0)
        {
            ret = ::read(fd, buf, sizeof(buf) < size ? sizeof(buf): size);
            if (EVP_DigestUpdate(mdctx, buf, ret) != 1)
            {
                // 错误处理
                EVP_MD_CTX_free(mdctx);
                close(fd);
                return;
            }

            size -= ret;
        }

        if (ret < 0)
        {
            // 处理读取错误
            EVP_MD_CTX_free(mdctx);
            close(fd);
            return;
        }

        unsigned char result[MD5_DIGEST_LENGTH];
        unsigned int len;
        if (EVP_DigestFinal_ex(mdctx, result, &len) != 1)
        {
            // 错误处理
            EVP_MD_CTX_free(mdctx);
            close(fd);
            return;
        }

        EVP_MD_CTX_free(mdctx);
        close(fd);

        char hex[33]; // MD5 32字符 + '\0'
        for (int i = 0; i < MD5_DIGEST_LENGTH; ++i)
        {
            sprintf(hex + i * 2, "%02x", result[i]);
        }
        hex[32] = '\0';
        md5val = string(hex);
        /* md5val.clear();

         int fd = open(path.c_str(), O_RDONLY);

         MD5_CTX md5Context;
         MD5_Init(&md5Context);

         char buf[1024 * 16];
         int ret{};
         while ((ret = ::read(fd, buf, sizeof(buf))))
         {
             MD5_Update(&md5Context, buf, ret);
         }

         unsigned char result[MD5_DIGEST_LENGTH];
         MD5_Final(result, &md5Context);

         char hex[35];
         memset(hex, 0, sizeof(hex));
         for (int i = 0; i < MD5_DIGEST_LENGTH; ++i)
         {
             sprintf(hex + i * 2, "%02x", result[i]);
         }
         hex[32] = '\0';
         md5val = string(hex);

         return;
     } */
    }
};